package com.cloudpark.controller;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.cloudpark.common.mqtt.MqttDTO;
import com.cloudpark.common.mqtt.QueryVehicleDTO;
import com.cloudpark.common.mqtt.QueryVehicleResultDTO;
import com.cloudpark.common.util.Constants;
import com.cloudpark.common.util.ObjectUtil;
import com.cloudpark.common.util.UuidUtil;
import com.cloudpark.common.util.wechat.MsgJsonUtil;
import com.cloudpark.common.util.wechat.MsgRequest;
import com.cloudpark.common.util.wechat.MsgText;
import com.cloudpark.common.util.wechat.MsgXmlUtil;
import com.cloudpark.common.util.wechat.SignUtil;
import com.cloudpark.common.util.wechat.WxManagerUtil;
import com.cloudpark.model.entity.EstateWechat;
import com.cloudpark.model.entity.MqttMessage;
import com.cloudpark.model.entity.User;
import com.cloudpark.model.vo.PlateVo;
import com.cloudpark.mqtt.MQTTPub;
import com.cloudpark.service.EstateService;
import com.cloudpark.service.MqttMessageService;
import com.cloudpark.service.PlateService;
import com.cloudpark.service.UserService;

@Controller
@RequestMapping("/api")
public class WeChatEventController {

	private final Logger log = Logger.getLogger(this.getClass());
	
	@Autowired
	private EstateService estateService;
	@Autowired
	private UserService userService;
	@Autowired
	private PlateService plateService;
	@Autowired
	private MqttMessageService mqttMessageService;
	
	/**
	 * 接口正确性校验
	 * @param request
	 * @param response
	 * @return
	 */
    @RequestMapping(value = "/message", method = RequestMethod.GET)
    public String messageGet(HttpServletRequest request, HttpServletResponse response) {
        try {
            // 微信加密签名
            String signature = request.getParameter("signature");
            // 时间戳
            String timestamp = request.getParameter("timestamp");
            // 随机数
            String nonce = request.getParameter("nonce");
            // 随机字符串
            String echostr = request.getParameter("echostr");
            PrintWriter out = response.getWriter();
            // 请求校验，若校验成功则原样返回echostr，表示接入成功，否则接入失败
            log.info("signature:" + signature);
            log.info("timestamp:" + timestamp);
            log.info("nonce:" + nonce);
            log.info("echostr:" + echostr);

            if (SignUtil.checkSignature(signature, timestamp, nonce)) {
                out.print(echostr);
            }
            out.close();
            out = null;
        } catch (Exception e) {
            log.error("微信接口正确性校验异常", e);
        }
        return null;
    }

    /**
     * 微信服务端接口事件消息处理
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/message", method = RequestMethod.POST)
    public String messagePost(HttpServletRequest request, HttpServletResponse response) {
        try {
        	request.setCharacterEncoding("UTF-8");
            response.setCharacterEncoding("UTF-8"); // 乱码问题
            PrintWriter out = response.getWriter();
            MsgRequest msgRequest = MsgXmlUtil.parseXml(request);// 获取发送的消息
            out.print(processMsg(msgRequest, request));
        } catch (Exception e) {
        	log.error("微信接口事件消息处理异常", e);
        }
        return null;
    }
    
    private String processMsg(MsgRequest msgRequest, HttpServletRequest request) {
    	log.info("公众号请求参数params=" + msgRequest.toString());
        String msgtype = msgRequest.getMsgType();// 接收到的消息类型
        String respXml = null;// 返回的内容
        if (msgtype.equals("text")) {// 文本消息

        } else if (msgtype.equals("event")) {// 事件消息
            respXml = this.processEventMsg(msgRequest, request);
        } else if (msgtype.equals("image")) {// 图片消息

        } else if (msgtype.equals("location")) {// 地理位置消息
            MsgText text = new MsgText();
            text.setContent("地理位置消息---------" + msgRequest.getFromUserName() + "---" + msgRequest.getLocation_X() + "---" + msgRequest.getLocation_Y());
            return MsgXmlUtil.textToXml(WxManagerUtil.getMsgResponseText(msgRequest, text));
        }
        return respXml;
    }

    // 处理事件消息
    private String processEventMsg(MsgRequest msgRequest, HttpServletRequest request) {
        String event = msgRequest.getEvent();
        String developerId = msgRequest.getToUserName(); // 开发者微信号
        String openId = msgRequest.getFromUserName(); // 用户标识
        if ("subscribe".equals(event)) {// 订阅消息
        	EstateWechat estateWechat = estateService.queryEstateWechatByDeveloperId(developerId);
        	//获取昵称
        	JSONObject jsonObject = WxManagerUtil.getUserInfo(estateWechat.getAppId(), estateWechat.getAppSecret(), openId);
            String nickname = jsonObject.getString("nickname");
        	User user = userService.findUserByOpenId(openId);
        	if (null == user) {
        		user = new User();
        		user.setCreatedTime(new Date());
        	}
        	user.setOpenId(openId);
        	user.setStatus(Constants.SUBSCRIBE);
        	user.setNickname(nickname);
        	user.setUpdateTime(new Date());
        	if (null != estateWechat && ObjectUtil.isNotBlank(estateWechat.getToken())) {
        		user.setToken(estateWechat.getToken());
        	}
        	userService.saveUser(user);
            MsgText text = new MsgText();
            if (null != estateWechat && ObjectUtil.isNotBlank(estateWechat.getName())) {
            	text.setContent("欢迎订阅"+estateWechat.getName()+"!");
            } else {
            	text.setContent("欢迎订阅!");
            }
            return MsgXmlUtil.textToXml(WxManagerUtil.getMsgResponseText(msgRequest, text));
        } else if ("unsubscribe".equals(event)) {// 取消订阅消息
        	User user = userService.findUserByOpenId(openId);
        	if (null != user) {
        		user.setStatus(Constants.UNSUBSCRIBE);
        		user.setUpdateTime(new Date());
        		userService.saveUser(user);
        	}
        } else if (event.equals("CLICK")) {// 点击事件消息
            String key = msgRequest.getEventKey();
            if (key.equals("QUERY_FEE")) // 停车缴费处理
            {
            	EstateWechat estateWechat = estateService.queryEstateWechatByDeveloperId(developerId);
                MsgText msgText = queryFee(openId, estateWechat, request);
                if (null == msgText) {
                    return ""; // 避免超时时微信重新请求
                }
                return MsgXmlUtil.textToXml(WxManagerUtil.getMsgResponseText(msgRequest, msgText));
            }
        } else if (event.equals("VIEW")) {

        }
        return "";
    }

	private MsgText queryFee(String openId, EstateWechat estateWechat, HttpServletRequest request) {
    	User user = userService.findUserByOpenId(openId);
    	List<PlateVo> list = plateService.queryPlateList(user.getId());
    	if (ObjectUtil.isBlank(list)) {
    		MsgText msgText = new MsgText();
    		 String urlString = "wechat/vehicle";
    		 StringBuilder sb = new StringBuilder();
             sb.append("您尚未绑定车辆，请先到【我的】-")
                 .append("<a href=\"").append(Constants.baseUrl).append(urlString).append("?ecode=").append(user.getToken())
                 .append("\" >【我的车辆】</a>").append("界面绑定您的车辆。");
             msgText.setContent(sb.toString());
             return msgText;
    	} else {
    		// send mqtt message
    		MqttDTO<QueryVehicleDTO> mqttDTO = new MqttDTO<QueryVehicleDTO>();
    		List<QueryVehicleDTO> dataItems = new ArrayList<QueryVehicleDTO>();
    		for (PlateVo plateVo : list) {
    			QueryVehicleDTO queryVehicleDTO = new QueryVehicleDTO();
    			queryVehicleDTO.setPlateNumber(plateVo.getPlateNumber());
    			queryVehicleDTO.setBusinessCode(estateWechat.getToken());
    			dataItems.add(queryVehicleDTO);
    		}
    		mqttDTO.setCode(Constants.OK);
    		mqttDTO.setServiceId(Constants.PAY_QUERY_VEHICLE);
    		mqttDTO.setUuid(UuidUtil.getUUID());
    		mqttDTO.setDataItems(dataItems);
    		String sendMessage = JSON.toJSONString(mqttDTO);
    		log.info("query vehicle by platenumber " + sendMessage);
    		
    		MqttMessage mqttMessage = new MqttMessage();
    		mqttMessage.setUuid(mqttDTO.getUuid());
    		mqttMessage.setSponsor(Constants.MQTT_SPONSOR_CLOUDPARK);
    		mqttMessage.setSendMessage(sendMessage);
    		mqttMessage.setSendStatus(Constants.MQTT_STATUS_SENDIING);
    		mqttMessage.setSendTime(new Date());
    		mqttMessage.setCreatedTime(new Date());
    		mqttMessageService.save(mqttMessage);
    		boolean success = MQTTPub.getSingleton().publish(sendMessage);
    		if (success) {
    			mqttMessage.setSendStatus(Constants.MQTT_STATUS_SENDED);
    			mqttMessageService.update(mqttMessage);
    		}
    		
    		// query mqtt result from db
    		mqttMessage = mqttMessageService.queryById(mqttMessage.getId());
    		if (null != mqttMessage.getReceiveStatus() && mqttMessage.getReceiveStatus().intValue() == Constants.MQTT_STATUS_RECEIVED) {
    			queryVehicleByPlate(mqttMessage, openId, estateWechat);
    		} else {
    			try {
    				long sleepTimes = 2000l;
    				log.info(Constants.PAY_QUERY_VEHICLE + " waiting for mqtt callback result, sleeping "+sleepTimes+" ms");
					Thread.sleep(sleepTimes);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
    			mqttMessage = mqttMessageService.queryById(mqttMessage.getId());
    			if (null != mqttMessage.getReceiveStatus() && mqttMessage.getReceiveStatus().intValue() == Constants.MQTT_STATUS_RECEIVED) {
    				queryVehicleByPlate(mqttMessage, openId, estateWechat);
        		}
    		}
    	}
		return null;
	}

	private void queryVehicleByPlate(MqttMessage mqttMessage, String openId,
			EstateWechat estateWechat) {
		StringBuilder sb = new StringBuilder(); 
		if (ObjectUtil.isNotBlank(mqttMessage.getReceiveMessage())) {
			JSONObject jsonObject = JSON.parseObject(mqttMessage.getReceiveMessage());
	        String dataItems = jsonObject.getString("dataItems");
	        List<QueryVehicleResultDTO> queryVehicleResultDTOs = JSON.parseArray(dataItems, QueryVehicleResultDTO.class);
	        int len = queryVehicleResultDTOs.size();
	        if (len>=1) {
            	sb.append("查询到您的停车记录：\r\n\n");
	        	for (QueryVehicleResultDTO resultQueryVehicleDTO : queryVehicleResultDTOs) {
	        		sb.append("车牌号：").append(resultQueryVehicleDTO.getPlateNumber()).append("\r\n");
                    sb.append("入场时间：").append(resultQueryVehicleDTO.getEnterTime()).append("\r\n");
                    if (len > 1) {
	                    sb.append("<a href=\"").append(Constants.baseUrl).append("wechat/pay")
	                        .append("?plateNumber=").append(resultQueryVehicleDTO.getPlateNumber())
	                        .append("&parkCode=").append(resultQueryVehicleDTO.getParkCode())
	                        .append("&ecode=").append(estateWechat.getToken())
	                        .append("\" >查看详情</a> ").append("\r\n\n");
                    } else {
                        sb.append("\r\n").append("你可以点击详情").append("查询停车账单，支付完停车费然后离开停车场。\r\n")
                            .append("<a href=\"").append(Constants.baseUrl).append("wechat/pay")
                            .append("?plateNumber=").append(resultQueryVehicleDTO.getPlateNumber())
                            .append("&parkCode=").append(resultQueryVehicleDTO.getParkCode())
                            .append("&ecode=").append(estateWechat.getToken())
                            .append("\" >查看详情</a> ");
                    }
		        }
	        	// more than one records
                if (len > 1) {
                	sb.append("你可以点击详情")
                    	.append("查询停车账单，支付完停车费然后离开停车场。");
                }
	        } else {
	        	sb.append("您的车辆不在停车场内。");
	        }
		} else {
			sb.append("您的车辆不在停车场内。");
		}
		String message = MsgJsonUtil.toJSONString(sb.toString(), openId);
		WxManagerUtil.customMessage(message, estateWechat.getAppId(), estateWechat.getAppSecret());
	}
}